﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZCConsole.VOBC
{
    class UpdateTrainPosition
    {
        TrainInfo CurrentTrain;
        public Dictionary<UInt16, TrainInfo> PreTrainPosition = new Dictionary<UInt16, TrainInfo>();
        List<Device> DeviceNeedToChange = new List<Device>();
        ZC zc;

        public UpdateTrainPosition(ZC zc)
        {
            this.zc = zc;
        }

        public void SetTrainInfo(TrainInfo VOBC)
        {
            this.CurrentTrain = VOBC;
            if (PreTrainPosition.Keys.Contains(CurrentTrain.NIDTrain)
                && PreTrainPosition[CurrentTrain.NIDTrain].EqualTo(CurrentTrain))
            { }
            else
            {
                CancelPreTrainPosition();
                UpDateCurrentTrainPosition();
                UpdatePrePosition();
            }
        }

        private void UpdatePrePosition()
        {
            if (PreTrainPosition.Keys.Contains(CurrentTrain.NIDTrain))
            {
                PreTrainPosition[CurrentTrain.NIDTrain] = CurrentTrain;
            }
            else
            {
                PreTrainPosition.Add(CurrentTrain.NIDTrain, CurrentTrain);
            }
        }

        /// <summary>
        /// 设置新的列车占用信息
        /// </summary>
        private void UpDateCurrentTrainPosition()
        {
            ChangeDeviceOccupy(CurrentTrain.HeadPosition, CurrentTrain.HeadOffset, CurrentTrain.TrainDirection, true);
            ChangeDeviceOccupy(CurrentTrain.TailPosition, CurrentTrain.TailOffset, CurrentTrain.TrainDirection, true);
        }

        /// <summary>
        /// 取消之前的列车占用信息
        /// </summary>
        private void CancelPreTrainPosition()
        {
            if (PreTrainPosition.Keys.Contains(CurrentTrain.NIDTrain))
            {
                ChangeDeviceOccupy(PreTrainPosition[CurrentTrain.NIDTrain].HeadPosition, 
                    PreTrainPosition[CurrentTrain.NIDTrain].HeadOffset, 
                    PreTrainPosition[CurrentTrain.NIDTrain].TrainDirection, false);
                ChangeDeviceOccupy(PreTrainPosition[CurrentTrain.NIDTrain].TailPosition, 
                    PreTrainPosition[CurrentTrain.NIDTrain].TailOffset, 
                    PreTrainPosition[CurrentTrain.NIDTrain].TrainDirection, false);
            }
        }

        /// <summary>
        /// 改变区段或道岔的占用状态
        /// </summary>
        /// <param name="position"></param>
        /// <param name="offset"></param>
        /// <param name="trainDirection"></param>
        /// <param name="isOccupy"></param>
        private void ChangeDeviceOccupy(Device position, uint offset, TrainDir trainDirection, bool isOccupy)
        {
            if (position is Section)
            {
                (position as Section).SetTrainOccupy(trainDirection, offset, isOccupy, CurrentTrain.NIDTrain);
                AddToDeviceNeedToChange(position);
            }
            else if (position is RailSwitch)
            {
                ChangeRailSwitchOccupy(position as RailSwitch, isOccupy);
            }
        }

        /// <summary>
        /// 实现道岔占用状态的改变
        /// </summary>
        /// <param name="railSwitch"></param>
        /// <param name="isOccupy"></param>
        private void ChangeRailSwitchOccupy(RailSwitch railSwitch, bool isOccupy)
        {
            railSwitch.SetTrainOccupy(CurrentTrain.NIDTrain, isOccupy);
            AddToDeviceNeedToChange(railSwitch);
            RailSwitch needToChange = FindAnotherRailswitch(railSwitch);
            if (needToChange != null)
            {
                needToChange.SetTrainOccupy(CurrentTrain.NIDTrain, isOccupy);
                AddToDeviceNeedToChange(needToChange);          //如果区段内存在另一个道岔，则另一个道岔的占用状态一起改变
            }
        }

        public RailSwitch FindAnotherRailswitch(RailSwitch railswitch)
        {
            RailSwitch railNeedToChange = zc.data.Devices.Find((Device element) =>
            {
                if (element is RailSwitch)
                {
                    if ((element as RailSwitch).section.Name == railswitch.section.Name && (element as RailSwitch).Name != railswitch.Name)
                    {
                        return true;
                    }
                }
                return false;
            }) as RailSwitch;
            return railNeedToChange;
        }

        /// <summary>
        /// 将需要改变占用状态的设备存入列表DeviceNeedToChange
        /// </summary>
        /// <param name="device"></param>
        private void AddToDeviceNeedToChange(Device device)
        {
            if (!DeviceNeedToChange.Contains(device))
            {
                DeviceNeedToChange.Add(device);
            }
        }
    }
}